<?php

namespace common\model\sell66;

use common\db\Sell66;
use common\service\act\RaffleService;
use common\service\AdditionService;
use common\service\ScoreService;
use common\service\UserPointService;
use common\service\UserService;
use common\service\act\CommissionService;
use think\Exception;
use think\Log;

/**
 * 机器人收装备的订单表
 * 
 * @author Administrator
 *        
 */
class UserOrder extends Sell66 {
	// 设置当前模型对应的完整数据表名称
	protected $table = 'from_trade';
	protected $pk = 'user_order_id';
	
	const  ROUND_ROBIN_TIME = 15;
	const  CANNEL_ROUND_ROBIN_TIME = 2;
	
	/**
	 * 第三方报价状态
	 * 
	 * @var unknown
	 */
	public static $orderStatusMaps = [ 
			'invalid' => - 1, // 无效的
			'create' => 1, // 交易中
			'success' => 2, // 成功
			'failed' => 3  // 失败
	];
	public static $tradeOfferStatusMap = [
			'reading' => -1, // 等待发起报价
			'success' => 3, // 成功
			'create' => 2,  //
			'canceled'=>6,
			'deny'	=> 7, // 拒绝报价
			'hang_up' => 11,
			'special' => 99, //取消订单失败异常状态
	];
	public static $currency = [ 
			'CNY' => 1 
	];
	
	public static $lockMaps = [
		'lock'=>1,
		'default'=>0
	];
	public static $orderSourceTypeMap = [ 
			'robot_buy' => 'robot_buy'  // 机器人购买
	];
	public function orderdetails() {
		return $this->hasMany ( UserOrderDetail::getClassName (), 'user_order_id', 'user_order_id' );
	}
	
	public function steam(){
		return $this->hasOne(UserSteam::getClassName(), 'steam_id', 'steam_id');
	}
	public function user(){
	    return $this->hasOne(User::getClassName(), 'user_id', 'user_id');
    }
	
	public static function getlastCreatingOrder($userId){
		return static::where ( [
				'tradeoffer_status' => self::$tradeOfferStatusMap ['create'],
				'order_status' => self::$orderStatusMaps ['create'],
				'user_id'=>$userId
				] )->where('expire_time','>',time())->order ( 'created_time desc' )
				->find ();
	}
	public static function createOrder($order_data) {
		$connection = ( new self ())->db();
		$connection->startTrans();
		$userOrderModel = new self ();
		$userOrderModel->user_id = $order_data ['user_id'];
		$userOrderModel->bot_id = $order_data ['bot_id'];
		$userOrderModel->steam_id = $order_data ['steam_id'];
		$userOrderModel->currency = self::$currency ['CNY'];
		$userOrderModel->price = $order_data ['price'];
		$userOrderModel->app_id = $order_data ['app_id'];
		$userOrderModel->verify_code = $order_data ['verify_code'];
		$userOrderModel->user_bank_id = $order_data ['user_bank_id'];
		$userOrderModel->origin_price = $order_data ['origin_price'];
		$userOrderModel->discount_price = $order_data ['discount_price'];
		$userOrderModel->note = empty ( $order_data ['note'] ) ? "" : $order_data ['note'];
		$userOrderModel->orderno = $userOrderModel->createOrderNo ();
		$userOrderModel->plus_ratio = $order_data['plus_ratio'];
		$userOrderModel->tradeoffer_id = $order_data ['tradeoffer_id'];
		$userOrderModel->plus_ratio_info = $order_data ['plus_ratio_info'];
		$userOrderModel->user_bank_id = $order_data ['user_bank_id'];
		$userOrderModel->tradeoffer_status = -1;
		$userOrderModel->order_status = self::$orderStatusMaps ['create'];
		$userOrderModel->tradeoffer = $order_data ['tradeoffer'];
		$userOrderModel->amount = $order_data ['amount'];
		$userOrderModel->expire_time = time() + 300;
		$userOrderModel->last_sure_time = time();
		if (! $userOrderModel->save ()) {
			$connection->rollback();
			return false;
		}
		
		$assentItems = $order_data ['assent_items'];
		$userOrderArr = $userOrderModel->toArray ();
		$result = UserOrderDetail::createUserOrderDetail ( $userOrderArr, $assentItems );
		if (! $result) {
			$connection->rollback();
			return false;
		}
		$connection->commit();
		// TODO 订单日志
		
		return $userOrderArr['user_order_id'];
	}
	private function createOrderNo() {
		return date ( 'Ymd' ) . str_pad ( mt_rand ( 1, 99999 ), 5, '0', STR_PAD_LEFT );
	}
	public static function getTradingOrder($botId, $rangeTime = false, $limit = false) {
		$whereCond = [ 
				'bot_id' => $botId,
				'order_status' => self::$orderStatusMaps ['create'] 
		];
		$query = static::where ( $whereCond );
		if ($limit != false) {
			$query->limit ( $limit );
		}
		$list = $query->select ();
		return $list;
	}
	public function unlock(){
		$this->lock = self::$lockMaps['default'];
		$this->save();
	}
	public function lock(){
		$this->lock = self::$lockMaps['lock'];
		$this->save();
	}
	public  function getOneTradingOrder() {
		$result =  $this->where ( [ 
				'tradeoffer_status' => self::$tradeOfferStatusMap ['create'],
				'order_status' => self::$orderStatusMaps ['create'],
				'lock'=>self::$lockMaps['default']
				] )->where('tradeoffer_id', '>', 0)->order (['round_robin_time'=>'asc','created_time'=>'asc'])
			->find ();
		if(!empty($result)){
			$result->lock();
			return $result;
		}
		return false;
	}
	
	
	public function getOneExpireTradingOrder($time=300){
		
		$result =  $this->where ( [
				'tradeoffer_status' => self::$tradeOfferStatusMap ['create'],
				'order_status' => self::$orderStatusMaps ['create'],
				'lock'=>self::$lockMaps['default']
				] )->where('created_time','<',time()-$time)->order ( 'created_time asc' )
				->find ();
		if(!empty($result) && $result->lock()){
			return $result;
		}
		return false;
	}

	/**
	 * 获取取消异常订单
	 * @return array
	 */
	public static function getCancelErrUserOrder($startTime = NULL, $endTime = NULL)
	{
		$where = array(
			'tradeoffer_status' => self::$tradeOfferStatusMap['special'],
			//'order_status' => self::$orderStatusMaps['failed'],
			'lock' => self::$lockMaps['default'],
			'created_time' => array('between', array($startTime, $endTime)),
			'cannel_robin_time' => array('>', 0),
		);
		return static::where($where)->order('created_time asc')->select();
	}

	public static function getUserTradingOrder($userId,$time=300) {
		$startTime = time()-$time;
		$list = static::where([ 
				'tradeoffer_status' => self::$tradeOfferStatusMap ['create'],
				//'order_status' => self::$orderStatusMaps ['create'],
				'user_id'=>$userId
				])->where('created_time','>=',$startTime)->find();
		return $list;
	}
	/**
		取消订单 
	 */
	public static function cannelOrderByOrderId($userId,$orderId,$isSendMail=true){
		$result =   static::where(['user_order_id'=>$orderId,'user_id'=>$userId])->update(
					['order_status'=>self::$orderStatusMaps ['failed'],
					'tradeoffer_status' => self::$tradeOfferStatusMap['canceled'],
					]
				);
		if($result){
			return true;
		}
		return false;
	}
	
	public static function updateOrderStatusByTraderOfferStatus($order, $tradeOfferStatus) {
		
		if ($tradeOfferStatus == self::$tradeOfferStatusMap ['success'] && $order->tradeoffer_status != $tradeOfferStatus) {
			
			$connection = (new self())->db();
			// 更新订单状态
			$connection->startTrans();
			echo "start update order \n";
			try {
				$price =$order['price'];
				$orderId = $order['user_order_id'];
				$userId = $order['user_id'];
				$type = self::$orderSourceTypeMap ['robot_buy'];
				echo "start addUserBalance \n";
				$userBalance = UserBalance::addUserBalance ($userId,$price,$orderId, $type );
				if(empty($userBalance)){
					Log::record('add user balance failed, user_id : '.$userId);
					$connection->rollback();
					return false;
				}
				$userBankId = $order['user_bank_id'];
				$withdrawNo = $order['withdraw_no'];
				$payWay = '钱包';
				if($userBankId != 0){
					$withdrawBank = UserBank::get(['user_bank_id'=>$userBankId,'user_id'=>$userId]);
					$payWay = $withdrawBank['bank_name'];
					$money = $userBalance['balance'];
					$withdrawStatus = UserWithdrawRecord::createWithdraw($userId, $userBankId, $money, $userBalance,false);
					if(empty($withdrawStatus)){
						Log::record('create user withdraw record failed, user_id : '.$userId);
						$connection->rollback();
						return false;
					}else{
						$withdrawNo = $withdrawStatus['withdrawNo'];
					}
				}
				UserOrder::where(['user_order_id'=>$order['user_order_id']])->update(
					['order_status'=>self::$orderStatusMaps['success'],
					'tradeoffer_status'=>self::$tradeOfferStatusMap['success'],
					'finished_time'=>time(),
					'withdraw_no' => $withdrawNo
					]);
				$score = intval( $order['price'] );
				ScoreService::getInstance()->addUserScore($userId,$score);
				$connection->commit();
				if(getenv('commission_open') == 1){
					CommissionService::getInstance()->createOrderCommission($orderId, $userId);
				}

				// 7.31 TI7活动期间内 每1块给100积分
                if(RaffleService::getInstance()->checkActTime()){
                    UserPointService::getInstance()->addSellPoint($userId, 'TI7', 2, $price);
                }

				return array("code"=>true,'payWay'=>$payWay);
			} catch (\Exception $e) {
				echo $e->getMessage();
				$connection->rollback();
				return false;
			}
			
		} elseif ($order['tradeoffer_status'] != $tradeOfferStatus) {
			// steam tradeofferstate change
			UserOrder::where(['user_order_id'=>$order['user_order_id']])->update(
			['order_status' => self::$orderStatusMaps ['failed'],
			'tradeoffer_status' => $tradeOfferStatus
			]
			);
			echo "order failed \n";
			return 'cannel';
		}
	}
	
	public static function getFinishedOrderCount() {
		return static::where ( [ 
				'order_status' => self::$orderStatusMaps ['success'] 
		] )->count ();
	}
	
	/**
	 * 返回最近交易订单
	 */
	public static function getNearFinishedOrders($limit = 6) {
		return static::where ( [ 
				'order_status' => self::$orderStatusMaps ['success']
		] )->limit($limit)->order ( [ 
				'finished_time' => 'desc' 
		] )->select ();
	}
	public static function getOrderByOrderNo($userId,$orderNo) {
		return static::get ( [ 
				'orderno' => $orderNo,
				'user_id' => $userId
		] );
	}

    public static function getOrderByOrderId($userId, $orderId) {
        return static::get (['user_id'=>$userId, 'user_order_id'=>$orderId]);
    }
	
	public static function updateCannelTradeOfferMiss($order){
		if($order->cannel_robin_time >= self::CANNEL_ROUND_ROBIN_TIME ){
			// 标记取消未成功订单，bot/cancelOrderReview 脚本复查
			 UserOrder::where([ 'user_order_id'=>$order['user_order_id']])
			->update(
					[
					//'order_status'=>self::$orderStatusMaps['failed'],
					'tradeoffer_status'=>self::$tradeOfferStatusMap['special'],
					'last_cannel_time'=>time()
					]
			);
			return 'cancel';
		}else{
			 UserOrder::where([ 'user_order_id'=>$order['user_order_id']])
			->inc('cannel_robin_time')
			->update(['last_cannel_time'=>time()]);
			return true;
		}
	}
	
	public static function updateSureTradeOfferMiss($order){
		if($order->round_robin_time >= self::ROUND_ROBIN_TIME ){
			return UserOrder::where([ 'user_order_id'=>$order['user_order_id']])
					->update(
							['order_status'=>self::$orderStatusMaps['failed'],
							 'last_sure_time'=>time()
							]
							);
		}else{
			return UserOrder::where([ 'user_order_id'=>$order['user_order_id']])
			->inc('round_robin_time')
			->update(['last_sure_time'=>time()]);
		}
	}

	public static function getTopOrderDetails($startTime, $lastTime, $limit = 10)
	{
		$where = array(
			'order_status' => self::$orderStatusMaps ['success']
		);

		$result = static::alias('o')
			->join('user_steam s', 'o.user_id = s.user_id')
			->field('count(*) as num,o.user_id,s.personaname,s.avatarmedium,sum(o.price) as total_price')
			->where($where)
			->where('o.created_time', '>=', $startTime)->where('o.created_time', '<', $lastTime)
			->limit($limit)->group('o.user_id')
			->order('num desc')
			->order('total_price desc')
			->order('o.user_id asc')->select();

		return !empty($result) ? collection($result)->toArray() : array();
	}

	public static function getUserOrderTotalNum($userId, $startTime = NULL, $lastTime = NULL)
	{
		$where = array(
			'o.user_id' => $userId,
			'o.order_status' => self::$orderStatusMaps ['success']
		);

		$query = static::alias('o')->join('user_steam s', 'o.user_id = s.user_id')->where($where);

		if ($startTime) {
			$query->where('o.created_time', '>=', $startTime);
		}

		if ($lastTime) {
			$query->where('o.created_time', '<', $lastTime);
		}


		return $query->count();
	}

	public static function getUserTopOrderRanking($startTime, $lastTime)
	{
		$where = array(
			'order_status' => self::$orderStatusMaps ['success']
		);

		$result = static::alias('o')
			->join('user_steam s', 'o.user_id = s.user_id')
			->field('count(*) as num,o.user_id,s.personaname,s.avatarmedium,sum(o.price) as total_price')
			->where($where)
			->where('o.created_time', '>=', $startTime)->where('o.created_time', '<', $lastTime)
			->group('o.user_id')
			->order('num desc')
			->order('total_price desc')
			->order('o.user_id asc')->select();

		return !empty($result) ? collection($result)->toArray() : array();
	}

	public static function updateUserOrderEscrowDate($userOrderId, $escrowEndDate)
	{
		$where = array(
			'user_order_id' => $userOrderId,
		);

		$field = array(
			'escrow_end_date' => $escrowEndDate
		);

		return static::where($where)->update($field);
	}

	public static function getUserOrderEscrow($userOrderId = 0)
	{
		$where = array(
			'tradeoffer_status' => self::$tradeOfferStatusMap['hang_up'],
		);

		if ($userOrderId > 0) {
			$where['user_order_id'] = $userOrderId;
		}

		$result = static::where($where)->where('escrow_end_date', '>', 0)->where('escrow_end_date', '<', time())->select();

		return !empty($result) ? collection($result)->toArray() : array();
	}

	public static function updateUserOrderEscrowStatus($userOrderId)
	{
		$where = array(
			'user_order_id' => $userOrderId,
		);

		$field = array(
			'tradeoffer_status' => self::$tradeOfferStatusMap['create'],
			'order_status' => self::$orderStatusMaps ['create'],
			'lock' => self::$lockMaps['default'],
		);

		return static::where($where)->update($field);
	}

	/**
	 * 获取交易报价成功，新物品ID未落地
	 * @param  int $botId 机器人ID
	 * @return array
	 */
	public static function getUserOrderFinish($userOrderId = 0)
	{
		$where = array(
		    'tradeoffer_status' => self::$tradeOfferStatusMap['success'],
		);

		$query = static::haswhere('orderdetails', function($q) use ($userOrderId)
		{
			$q->where('new_assetid', '=', '');
		});

		if ($userOrderId > 0) {
			$query->where('user_order.user_order_id', '=', $userOrderId);
		}

		$result = $query->where($where)->where('user_order.created_time', '>=', strtotime('2018-01-01'))->find();

		return !empty($result) ? $result->toArray() : array();
	}

    public static function getNeedCreateOffer($clientNo){
        $bots = Bot::where(['client_no'=>$clientNo])->select();
        $botIds = [];
        foreach ($bots as $bot){
            $botIds[] = $bot['id'];
        }
        $userOrders = static::where('bot_id', 'in', $botIds)->where(['tradeoffer_status'=>-1,'lock'=>0])->select();
        $userOrderIds = [];
        foreach($userOrders as $item){
            $userOrderIds[] = $item['user_order_id'];
        }
        UserOrder::where('user_order_id', 'in', $userOrderIds)->update(['lock'=>1]);
        return $userOrders;
    }

	/**
	 * 获取订单信息
	 * @param  int $steamId steamID
	 * @param  string $verifyCode 验证码
	 * @return array
	 */
    public static function getUserOrderByVerifyCode($steamId, $verifyCode)
    {
    	$where = array(
    		'steam_id' => $steamId,
    		'verify_code' => $verifyCode,
    	);

    	$result = static::where($where)->find();

    	return !empty($result) ? $result->toArray() : array();
    }

	/**
	 * 修改订单报价信息
	 * @param  int $userOrderId 订单ID
	 * @param  string $tradeofferId 报价ID
	 * @return array
	 */
    public static function updateUserOrderByTradeofferId($userOrderId, $tradeofferId)
    {
		$where = array(
			'user_order_id' => $userOrderId,
		);

		$field = array(
			'tradeoffer_id' => $tradeofferId,
			'tradeoffer_status' => self::$tradeOfferStatusMap['create'],
			'order_status' => self::$orderStatusMaps['create'],
			'lock' => self::$lockMaps['default'],
		);

		return static::where($where)->update($field);
    }

	/**
	 * 获取用户每日累计金额
	 * @param  int $userId 用户ID
	 * @param  int $startTime 开始时间
	 * @param  int $endTime 结束时间
	 * @return array
	 */
    public static function getUserOrderTotalAmount($userId, $startTime = NULL, $endTime = NULL)
    {
    	$where = array(
    		'user_id' => $userId,
    		'order_status' => self::$orderStatusMaps['success'],
    		'tradeoffer_status' => self::$tradeOfferStatusMap['success'],
    	);

    	$query = static::where($where);

    	if ($startTime) {
    		$query->where('finished_time', '>=', $startTime);
    	}

    	if ($endTime) {
    		$query->where('finished_time', '<', $endTime);
    	}

    	return $query->sum('price');
    }

    public static function doingOrders($userId)
    {
        return static::where('user_id', $userId)
            ->where('tradeoffer_status', '<>', self::$tradeOfferStatusMap['success'])
            ->where('tradeoffer_status', '<>', self::$tradeOfferStatusMap['canceled'])
            ->where('tradeoffer_status', '<>', self::$tradeOfferStatusMap['deny'])
            ->where('created_time', '<', time())
            ->where('created_time', '>', time() - 60 * 5)->select();
    }

    /**
     * 获取用户订单大于10元的数量
     * @param $userId
     * @param array $timeScope
     * @return int|string
     */
    public static function getB52OrderNumByUserId($userId, array $timeScope)
    {
        $between = array(
            strtotime($timeScope['startTime']),
            strtotime($timeScope['lastTime']),
        );
        $result = static::whereBetween('created_time', $between)->where('tradeoffer_status', '=', '3')->where('price', '>', 10)->where('user_id', '=', $userId)->count();
        return $result;
    }

    public static function updateUserOrderByFromTradeId($userOrderId, $fromTradeId)
    {
		$where = array(
			'user_order_id' => $userOrderId,
		);

		$field = array(
			'from_trade_id' => $fromTradeId,
		);

		return static::where($where)->update($field);
	}

	public static function getUserOrderByCheckAll($userOrderId = NULL)
	{
		$between = array(
			self::$tradeOfferStatusMap['reading'],
			self::$tradeOfferStatusMap['create'],
		);

		$where = array();
		if ($userOrderId) {
			$where['user_order_id'] = $userOrderId;
		}

		$result = static::where($where)->whereIn('tradeoffer_status', $between)->select();

		return !empty($result) ? collection($result)->toArray() : array();
	}

	public static function updateUserOrderStatus($userOrderId, $botId, $tradeofferId, $status)
	{
		$where = array(
			'user_order_id' => $userOrderId,
		);

		$field = array(
			'bot_id' => $botId,
			'tradeoffer_id' => $tradeofferId,
			'tradeoffer_status' => $status,
		);

		return static::where($where)->update($field);
	}

	public static function getUserOrderByReading($userOrderId = NULL)
	{

		$where = array(
			'tradeoffer_status' => self::$tradeOfferStatusMap['reading'],
		);

		if ($userOrderId) {
			$where['user_order_id'] = $userOrderId;
		}

		$result = static::field('user_order_id, user_id, steam_id, tradeoffer_id, tradeoffer_status, app_id, from_trade_id')->where($where)->where('from_trade_id', '<=', 0)->with('orderdetails')->select();
		
		return !empty($result) ? collection($result)->toArray() : array();
	}

	public static function updateUserOrder($userOrderId, $botId, $tradeofferId, $status, $details = NULL)
	{
		$connection = (new self())->db();
		$connection->startTrans();

		try {
			$res1 = self::updateUserOrderStatus($userOrderId, $botId, $tradeofferId, $status);
			if (!$res1) {
				throw new Exception('update user order failed, user_order_id:'.$userOrderId);
			}

			if ($details) {
				foreach ($details as $detail) {
					$data = array(
						'old_oid' => $detail['old_oid'],
						'new_oid' => $detail['new_oid'],
						'app_id' => $detail['app_id'],
						'bot_id' => $detail['bot_id'],
					);
					$res2 = UserOrderDetail::updateOrderByOrderId($userOrderId, $detail['old_oid'], $detail['new_oid']);
					if (!$res2) {
						throw new Exception('update user order new oid failed, data:'.json_encode($data));
					}
				}
			}

			$connection->commit();
			return true;
		} catch (\Exception $e) {
			echo $e->getMessage()."\r\n";
			$connection->rollback();
			return false;
		}
	}

	public static function getUserOrderByOrderId($userOrderId)
	{
		$where = array(
			'user_order_id' => $userOrderId,
		);

		$result = static::where($where)->with('orderdetails')->find();

		return !empty($result) ? $result->toArray() : array();
	}

	public static function getUserOrderByFromNotice($userId, $userOrderId = NULL)
	{
		$where = array(
			'user_id' => $userId,
		);

		$whereIn = array(
			self::$tradeOfferStatusMap['reading'],
			self::$tradeOfferStatusMap['create'],
		);

		$query = static::where($where);
		if ($userOrderId) {
			$query->where('user_order_id', '=', $userOrderId)->where('updated_time', '>=', (time() - 420));
		} else {
			$query->whereIn('tradeoffer_status', $whereIn);
		}

		$result = $query->select();

		return !empty($result) ? collection($result)->toArray() : array();
	}
}